package net.cmbt.okframe.oknet;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.google.gson.Gson;


import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;

import static net.cmbt.okframe.oknet.MD5.byteArrayToHexString;


/**
 * Created by Administrator on 2017/10/13.
 */

public class OkhttpTools implements Callback {

    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    private final OkHttpClient okHttpClient;
    private static final long cacheSize = 1024 * 1024 * 20;// 缓存文件最大限制大小20M
    private static String cacheDirectory = Environment.getExternalStorageDirectory() + "/okttpcaches"; // 设置缓存文件路径
    private static Cache cache = new Cache(new File(cacheDirectory), cacheSize);  //
    private Request request;
    MediaType jsonType = MediaType.parse("application/json; charset=utf-8");

    int RequestCode;
    Activity activity;
    AlertDialog.Builder builder;
    private AlertDialog show;
    View view;
    OkHttpListener mListner;
    private final Dialog dialog = null;

    Map<String, String> treeMaps = new TreeMap<String, String>(new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o2.compareTo(o1);  // 降序排列
        }
    });
    private String md5Str;
    private String szImei;
    private String request_data;

    public OkhttpTools(Activity activity, int RequestCode, OkHttpListener mListner) {
        okHttpClient = new OkHttpClient();
        this.RequestCode = RequestCode;
        this.mListner = mListner;
        this.activity = activity;
        OkPreferences.init(activity.getApplication());
        szImei = OkPreferences.getMobileNO();
        if (szImei == null) {
            szImei = "YPCKWGI359FRTROZU2OV5";
        }
    }


    /**
     * GET 请求
     *
     * @param RequestCode
     * @param url
     */
    public void get(int RequestCode, String url) {
        // showProgress();
        String accessToken = OkPreferences.getAccessToken();
        Log.e("", "token打印：" + accessToken);
        Request request = new Request.Builder().url(url).get()
                //强制使用网络响应
//                .header("Cache-Control", "no-cache") // 刷新数据
                .header("Authorization", "Bearer " + accessToken)
                .build();
        //通过服务器验证缓存数据是否有效
       /*         .header("Cache-Control", "max-age=0")
                .build();*/
        // 强制使用缓存响应
            /*    .header("Cache-Control", "only-if-cached")
                .build();*/
        //指定缓存数据过时的时间
     /*   int maxStale = 60 * 60 * 24 * 28; //4周
                .header("Cache-Control", "max-stale=" + maxStale)
                .url("http://publicobject.com/helloworld.txt")
                .build();*/

        request_data = url;

        try {
            if (dialog != null) {
                if (!dialog.isShowing()) {
                    dialog.show();
                }
            }
        } catch (Exception e) {

        }
        Call call = okHttpClient.newCall(request);
        call.enqueue(new OkhttpTools(activity, RequestCode, mListner));
    }


    /**
     * GET 请求
     *
     * @param RequestCode
     * @param url
     */
    public void get(int RequestCode, String url, String hearToken) {
        // showProgress();
        String accessToken = OkPreferences.getAccessToken();
        Log.e("", "token打印：" + accessToken);
        Request request = new Request.Builder().url(url).get()
                //强制使用网络响应
//                .header("Cache-Control", "no-cache") // 刷新数据
                .header("Authorization", "Bearer " + hearToken)
                .build();
        //通过服务器验证缓存数据是否有效
       /*         .header("Cache-Control", "max-age=0")
                .build();*/
        // 强制使用缓存响应
            /*    .header("Cache-Control", "only-if-cached")
                .build();*/
        //指定缓存数据过时的时间
     /*   int maxStale = 60 * 60 * 24 * 28; //4周
                .header("Cache-Control", "max-stale=" + maxStale)
                .url("http://publicobject.com/helloworld.txt")
                .build();*/
        try {


            if (dialog != null) {
                if (!dialog.isShowing()) {
                    dialog.show();
                }
            }
        } catch (Exception e) {

        }
        Call call = okHttpClient.newCall(request);
        call.enqueue(new OkhttpTools(activity, RequestCode, mListner));
    }


    /**
     * POST 提交json形式
     *
     * @param RequestCode
     * @param url
     * @param json
     */
    public void postJson(int RequestCode, String url, String json, String headValue) {

        RequestBody body = RequestBody.create(jsonType, json);
        String accessToken = OkPreferences.getAccessToken();
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .header("Authorization", "Bearer " + headValue)
                .build();

        try {
            if (dialog != null) {
                if (!dialog.isShowing()) {
                    dialog.show();
                }

            }
        } catch (Exception e) {

        }

        Call call = okHttpClient.newCall(request);
        call.enqueue(new OkhttpTools(activity, RequestCode, mListner));
    }

    /**
     * POST 提交json形式
     *
     * @param RequestCode
     * @param url
     * @param json
     */
    public void postJson(int RequestCode, String url, String json) {
        String accessToken = OkPreferences.getAccessToken();
        RequestBody body = RequestBody.create(jsonType, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .header("Authorization", "Bearer " + accessToken)
                .build();
        try {
            if (dialog != null) {
                if (!dialog.isShowing()) {
                    dialog.show();
                }
            }
        } catch (Exception e) {

        }
        Call call = okHttpClient.newCall(request);
        call.enqueue(new OkhttpTools(activity, RequestCode, mListner));
    }


    String str = "data:" + jsonType + ";base64," + jsonType;
    private static final String TAG = "uploadFile";
    private static final int TIME_OUT = 10 * 10000000; //超时时间
    private static final String CHARSET = "utf-8"; //设置编码
    private static final String PREFIX = "--";
    private static final String LINE_END = "\r\n";

    public interface FileUploadListener {
        public void onProgress(long pro, double precent);

        public void onFinish(int code, String res, Map<String, List<String>> headers);
    }

    public void upload(String host, File file, Map<String, String> params, final FileUploadListener listener) {
        String BOUNDARY = UUID.randomUUID().toString(); //边界标识 随机生成 String PREFIX = "--" , LINE_END = "\r\n";
        String CONTENT_TYPE = "multipart/form-data"; //内容类型
        try {
            URL url = new URL(host);
            final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(TIME_OUT);
            conn.setConnectTimeout(TIME_OUT);
            conn.setRequestMethod("POST"); //请求方式
            conn.setRequestProperty("Charset", CHARSET);//设置编码
            conn.setRequestProperty("connection", "keep-alive");
            conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
            conn.setDoInput(true); //允许输入流
            conn.setDoOutput(true); //允许输出流
            conn.setUseCaches(false); //不允许使用缓存
            if (file != null) {
                /** * 当文件不为空，把文件包装并且上传 */
                OutputStream outputSteam = conn.getOutputStream();
                DataOutputStream dos = new DataOutputStream(outputSteam);
                final StringBuffer sb = new StringBuffer();
                sb.append(LINE_END);
                if (params != null) {//根据格式，开始拼接文本参数
                    for (Map.Entry<String, String> entry : params.entrySet()) {
                        sb.append(PREFIX).append(BOUNDARY).append(LINE_END);//分界符
                        sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END);
                        sb.append("Content-Type: text/plain; charset=" + CHARSET + LINE_END);
                        sb.append("Content-Transfer-Encoding: 8bit" + LINE_END);
                        sb.append(LINE_END);
                        sb.append(entry.getValue());
                        sb.append(LINE_END);//换行！
                    }
                }
                sb.append(PREFIX);//开始拼接文件参数
                sb.append(BOUNDARY);
                sb.append(LINE_END);
                /**
                 * 这里重点注意：
                 * name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件
                 * filename是文件的名字，包含后缀名的 比如:abc.png
                 */
                sb.append("Content-Disposition: form-data; name=\"name\"; filename=\"" + file.getName() + "\"" + LINE_END);
                sb.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINE_END);
                sb.append(LINE_END);
                //写入文件数据
                dos.write(sb.toString().getBytes());
                InputStream is = new FileInputStream(file);
                byte[] bytes = new byte[1024];
                long totalbytes = file.length();
                long curbytes = 0;
                Log.i("cky", "total=" + totalbytes);
                int len = 0;
                while ((len = is.read(bytes)) != -1) {
                    curbytes += len;
                    dos.write(bytes, 0, len);
                    listener.onProgress(curbytes, 1.0d * curbytes / totalbytes);
                }
                is.close();
                dos.write(LINE_END.getBytes());
                byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes();
                dos.write(end_data);
                dos.flush();
                /**
                 * 获取响应码 200=成功
                 * 当响应成功，获取响应的流
                 */
                final int code = conn.getResponseCode();
                sb.setLength(0);
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        listener.onFinish(code, sb.toString(), conn.getHeaderFields());
                    }
                });
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public void doPostFImage(int RequestCode, final String url, final File file) {
        RequestBody body;
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
        builder.addFormDataPart("headPicture", file.getName(), RequestBody.create(MediaType.parse("image/jpg"), file));
        body = builder.build();
        Request request = new Request.Builder().post(body).url(url).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new OkhttpTools(activity, RequestCode, mListner));
    }


    //表单提交
    public void postForm(int RequestCode, String url, HashMap<String, String> treeMap) {
        HashMap<String, String> stringStringHashMap = new HashMap<>();
        LoginInfoBean.ResultBean.DataBean loginInfo = OkPreferences.getLoginInfo();
        treeMaps.clear();
        if (treeMap != null) {
            Iterator iterz = treeMap.entrySet().iterator();
            while (iterz.hasNext()) {
                Map.Entry entry = (Map.Entry) iterz.next();
                String key = (String) entry.getKey();
                String val = (String) entry.getValue();
                treeMaps.put(key, val);
            }
        }
        treeMaps.put("device_code", szImei);
        if (loginInfo != null) {
            treeMaps.put("uid", loginInfo.getId());
        }

        String paixuStr = "";
        for (String key : treeMaps.keySet()) {
            paixuStr += treeMaps.get(key);
        }
        String timeStame = TimeUtils.getTimeStame();
        try {
            String sha1 = sha1(paixuStr) + timeStame.substring(0, 10);
            md5Str = getMD5(sha1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //添加数据
        if (treeMap != null)
            stringStringHashMap = clone(treeMap);

        String s2 = new Gson().toJson(stringStringHashMap);

        stringStringHashMap.put("timestamp", timeStame.substring(0, 10));
        stringStringHashMap.put("sign", md5Str);
//        stringStringHashMap.put("device_code", "1111");
        stringStringHashMap.put("device_code", szImei);

        if (loginInfo != null) {
            stringStringHashMap.put("uid", loginInfo.getId());
        }

        request_data = new Gson().toJson(stringStringHashMap);


        Log.e("", "xxsddsdsdsffs::::" + request_data);

        okHttpClient.newBuilder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .build();

        FormBody.Builder builder = new FormBody.Builder();

        Iterator iter = stringStringHashMap.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            Object key = entry.getKey();
            Object val = entry.getValue();
            builder.add(key.toString(), val.toString());
        }

        FormBody formBody = builder.build();
        Request request = new Request.Builder()
                .url(url)//请求的url
                .post(formBody)
                .build();

        //创建/Call
        Call call = okHttpClient.newCall(request);
        call.enqueue(new OkhttpTools(activity, RequestCode, mListner));
    }


    //表单提交
    public void postImage(int RequestCode, String url, String base64) {
        okHttpClient.newBuilder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .build();

        FormBody.Builder builder = new FormBody.Builder();
        builder.addEncoded("", base64);
        FormBody formBody = builder.build();
        Request request = new Request.Builder()
                .url(url)//请求的url
                .post(formBody)
                .build();
        //创建/Call
        Call call = okHttpClient.newCall(request);
        call.enqueue(new OkhttpTools(activity, RequestCode, mListner));

    }


    @Override
    public void onFailure(Call call, final IOException e) {
        if (mListner != null) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mListner.onError(RequestCode, e);
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                if (NetUtils.getNetWorkStart(activity) == 1) {
//                                    ToastUtil.show(activity, "无网络");
                                }

                                if (dialog != null) {
                                    if (dialog.isShowing()) {
                                        dialog.dismiss();
                                    }

                                }
                            } catch (Exception e) {

                            }
                        }
                    });

                }
            });
        }
    }

    @Override
    public void onResponse(final Call call, Response response) throws IOException {
        if (mListner != null) {
            ResponseBody body = response.body();

            Log.e("缓存测试", "缓存" + response.cacheResponse());
            Log.e("缓存测试", "网络" + response.networkResponse());
            Log.e("============", "============缓存测试===============");

            final String string = body.string();
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try {

                        mListner.onSuccess(RequestCode, string,  request_data);

                        if (dialog != null) {
                            if (dialog.isShowing()) {
                                dialog.dismiss();
                            }
                        }

                    } catch (Exception e) {
                        Log.e("", "" + e.getMessage());
                        if (string.isEmpty()) {
                            Toast.makeText(activity, "服务器错误", Toast.LENGTH_SHORT).show();
                        } else {
//                            Toast.makeText(activity, "解析错误", Toast.LENGTH_SHORT).show();
                        }
                    }
                }
            });

        }
    }
/*
        public void showProgress(){
            builder  = new AlertDialog.Builder(activity);
            view = View.inflate(activity, R.layout.spots_dialog, null);
            builder.setView(view);
            show = builder.show();

        }*/


    /**
     * 对字符串进行MD5编码
     */
    private static String getMD5(String originString) {
        if (originString != null) {
            try {
                //创建具有指定算法名称的信息摘要
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                //使用指定的字节数组对摘要进行最后更新，然后完成摘要计算
                byte[] results = md5.digest(originString.getBytes());
                //将得到的字节数组变成字符串返回
                String result = byteArrayToHexString(results);
                return result;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    public static String encode(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(str.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }

    /**
     * sha1加密
     *
     * @param data
     * @return
     * @throws
     */
    public static String sha1(String data) throws NoSuchAlgorithmException {
        //信息摘要器算法名称
        MessageDigest md = MessageDigest.getInstance("SHA1");
        //把字符串转为字节数组
        byte[] b = data.getBytes();
        //使用指定的字节来更新我们的摘要
        md.update(b);
        //获取密文  （完成摘要计算）
        byte[] b2 = md.digest();
        //获取计算的长度
        int len = b2.length;
        //16进制字符串
        String str = "0123456789abcdef";
        //把字符串转为字符串数组
        char[] ch = str.toCharArray();

        //创建一个40位长度的字节数组
        char[] chs = new char[len * 2];
        //循环20次
        for (int i = 0, k = 0; i < len; i++) {
            byte b3 = b2[i];//获取摘要计算后的字节数组中的每个字节
            // >>>:无符号右移
            // &:按位与
            //0xf:0-15的数字
            chs[k++] = ch[b3 >>> 4 & 0xf];
            chs[k++] = ch[b3 & 0xf];
        }

        //字符数组转为字符串
        return new String(chs);
    }


    public static String getUTF8XMLString(String xml) {
        // A StringBuffer Object
        StringBuffer sb = new StringBuffer();
        sb.append(xml);
        String xmString = "";
        String xmlUTF8 = "";
        try {
            xmString = new String(sb.toString().getBytes("UTF-8"));
            xmlUTF8 = URLEncoder.encode(xmString, "UTF-8");
            System.out.println("utf-8 编码：" + xmlUTF8);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // return to String Formed
        return xmlUTF8;
    }


    public <T extends Serializable> T clone(T obj) {
        T clonedObj = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(obj);
            oos.close();
            ByteArrayInputStream bais = new ByteArrayInputStream(
                    baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            clonedObj = (T) ois.readObject();
            ois.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return clonedObj;
    }


}
